# -*- coding: utf-8 -*-

"""
  @author: tangliqi
  @date: 2022/11/30 17:38
  @python version: 3.6 
  @contact me: 110
  ---------------------------------------
  @desc: python设计模式实现 => 观察者模式.py
"""
from abc import abstractmethod


# 通过一个消息推送的例子来说明。
# 当我们希望某个消息推送给一批人，并且可以不断的添加或减少要推送的特定群体。
# 背后做的事情，就是维护一个推送列表，也即是观察者，当有新消息时，推送给列表中的所有群体。
# 观察者模式的构成：1.观察者抽象类 2.被观察者抽象类 3.具体的观察者类 4.具体的被观察者类

# ============================  抽象观察者类  ============================
class Observer:
    @abstractmethod
    def update(self):
        """观察者自己的方法"""
        pass


# ============================  抽象被观察者类  ============================
class Subject:
    def __init__(self):
        self.observer_list = []

    @abstractmethod
    def addObserver(self, observer: Observer):
        """添加一个观察者"""
        pass

    @abstractmethod
    def removeObserver(self, observer: Observer):
        """移除一个观察者"""
        pass

    @abstractmethod
    def notify(self):
        """通知所有观察者"""
        pass


# ============================  具体被观察者类  ============================
class ConcreteSubject(Subject):

    def addObserver(self, observer: Observer):
        self.observer_list.append(observer)

    def removeObserver(self, observer: Observer):
        self.observer_list.remove(observer)

    def notify(self):
        [i.update() for i in self.observer_list]


# ============================  具体观察者类  ============================
class ConcreteObserver1(Observer):
    def update(self):
        print("ConcreteObserver1 的 update 方法")


class ConcreteObserver2(Observer):
    def update(self):
        print("ConcreteObserver2 的 update 方法")


if __name__ == '__main__':
    # 创建一个主题，也就是被观察者
    subject = ConcreteSubject()

    # 添加两个观察者
    observer1, observer2 = ConcreteObserver1(), ConcreteObserver2()
    subject.addObserver(observer1)
    subject.addObserver(observer2)

    # 通知观察者
    subject.notify()
